require("IntercectionWithValuesInteractor")
require("IntercectionWithPropertyInteractor")
require("IntercectionWithEntitiesInteractorManager")

function UnitTests:testDecoherence()

	local stage =
	{
		Rooms =
		{
			Room1 =
			{			
			},
			
			Room2 =
			{	
			},
			
			Room3 =
			{	
			},
						
			Room4 =
			{	
			},	
						
			Room5 =
			{	
			},			
						
			Room6 =
			{	
			},			
		},
		
		Doors =
		{
			{
				Rooms = 
				{
					"Room1",
					"Room2"
				},
			},
			
			{
				Rooms = 
				{
					"Room2",
					"Room3"
				},
			},
			
			{
				Rooms = 
				{
					"Room3",
					"Room4"
				},
			},
			
			{
				Rooms = 
				{
					"Room4",
					"Room5"
				},
			},
			
			{
				Rooms = 
				{
					"Room5",
					"Room6"
				},
			},
		}		
	}
	
	local cast =
	{
		Player =
		{
			initialLocation = "Room1"
		},
	}
	
	local game = Game:new(stage, cast)
	
	local room1 = gField.entityTypes.Location.Room1
	local room2 = gField.entityTypes.Location.Room2
	local room3 = gField.entityTypes.Location.Room3
	local room4 = gField.entityTypes.Location.Room4
	local room5 = gField.entityTypes.Location.Room5
	local room6 = gField.entityTypes.Location.Room6

	local prop1 = Prop:new("prop1")
	prop1:addInteractor("CurrentContainer", IntercectionWithValuesInteractor:new({room2, room3}))

	local prop2 = Prop:new("prop2")
	prop2.properties["CurrentContainer"][room4] = nil
	local prop3 = Prop:new("prop3")
	prop3:addInteractor("CurrentContainer", IntercectionWithPropertyInteractor:new(prop2, "CurrentContainer"))

	local prop4 = Prop:new("prop4")
	prop4.properties["CurrentContainer"][room2] = nil
	local prop5 = Prop:new("prop5")
	prop5.properties["CurrentContainer"][room3] = nil
	local prop6 = Prop:new("prop6")
	prop6.properties["CurrentContainer"][room4] = nil
	local prop7 = Prop:new("prop7")
	prop7.properties["CurrentContainer"][room5] = nil
	
	IntercectionWithEntitiesInteractorManager:new({prop4, prop5, prop6, prop7}, "CurrentContainer")
	
	gRandom:addContextualBias({"Prop", "prop1", "CurrentContainer"}, room2)
	gRandom:addContextualBias({"Prop", "prop2", "CurrentContainer"}, room2)
	gRandom:addContextualBias({"Prop", "prop3", "CurrentContainer"}, room2)
	gRandom:addContextualBias({"Prop", "prop4", "CurrentContainer"}, room2)
	gRandom:addContextualBias({"Prop", "prop5", "CurrentContainer"}, room2)
	gRandom:addContextualBias({"Prop", "prop6", "CurrentContainer"}, room2)
	gRandom:addContextualBias({"Prop", "prop7", "CurrentContainer"}, room2)
		
	gGame:start()
	
	assert(not prop1:isPropertyCollasped("CurrentContainer"))
	
	assert(not prop1.decoheredProperties["CurrentContainer"][room1])		-- reduced outside
	assert(prop1.decoheredProperties["CurrentContainer"][room2] > 0)
	assert(prop1.decoheredProperties["CurrentContainer"][room3] > 0)
	assert(not prop1.decoheredProperties["CurrentContainer"][room4])		-- removed by IntercectionWithValuesInteractor
	assert(not prop1.decoheredProperties["CurrentContainer"][room5])		-- removed by IntercectionWithValuesInteractor
	assert(not prop1.decoheredProperties["CurrentContainer"][room6])		-- removed by IntercectionWithValuesInteractor

	assert(not prop3.decoheredProperties["CurrentContainer"][room1])		-- reduced outside
	assert(prop3.decoheredProperties["CurrentContainer"][room2] > 0)
	assert(prop3.decoheredProperties["CurrentContainer"][room3] > 0)
	assert(not prop3.decoheredProperties["CurrentContainer"][room4])		-- removed by IntercectionWithPropertyInteractor
	assert(prop3.decoheredProperties["CurrentContainer"][room5] > 0)
	assert(prop3.decoheredProperties["CurrentContainer"][room6] > 0)

	assert(not prop4.decoheredProperties["CurrentContainer"][room1])		-- reduced outside
	assert(not prop4.decoheredProperties["CurrentContainer"][room2])
	assert(not prop4.decoheredProperties["CurrentContainer"][room3])
	assert(not prop4.decoheredProperties["CurrentContainer"][room4])		
	assert(not prop4.decoheredProperties["CurrentContainer"][room5])
	assert(prop3.decoheredProperties["CurrentContainer"][room6] > 0)		-- only remaining common value between prop4->prop7

	assert(not prop5.decoheredProperties["CurrentContainer"][room1])		-- reduced outside
	assert(not prop5.decoheredProperties["CurrentContainer"][room2])
	assert(not prop5.decoheredProperties["CurrentContainer"][room3])
	assert(not prop5.decoheredProperties["CurrentContainer"][room4])		
	assert(not prop5.decoheredProperties["CurrentContainer"][room5])
	assert(prop5.decoheredProperties["CurrentContainer"][room6] > 0)		-- only remaining common value between prop4->prop7

	assert(not prop6.decoheredProperties["CurrentContainer"][room1])		-- reduced outside
	assert(not prop6.decoheredProperties["CurrentContainer"][room2])
	assert(not prop6.decoheredProperties["CurrentContainer"][room3])
	assert(not prop6.decoheredProperties["CurrentContainer"][room4])		
	assert(not prop6.decoheredProperties["CurrentContainer"][room5])
	assert(prop6.decoheredProperties["CurrentContainer"][room6] > 0)		-- only remaining common value between prop4->prop7

	assert(not prop7.decoheredProperties["CurrentContainer"][room1])		-- reduced outside
	assert(not prop7.decoheredProperties["CurrentContainer"][room2])
	assert(not prop7.decoheredProperties["CurrentContainer"][room3])
	assert(not prop7.decoheredProperties["CurrentContainer"][room4])		
	assert(not prop7.decoheredProperties["CurrentContainer"][room5])
	assert(prop7.decoheredProperties["CurrentContainer"][room6] > 0)		-- only remaining common value between prop4->prop7

	assert(not IntercectionWithValuesInteractor:new({room2, room3}):isAppliquableOn(prop7, "CurrentContainer"))
	assert(IntercectionWithValuesInteractor:new({room2, room6}):isAppliquableOn(prop7, "CurrentContainer"))

	gPlayer.body:execute("moveTo", room4)
	gGame:onBeat()
end